SQLiteは「1ファイルで完結する」軽量DBですが、 そのシンプルさゆえにセキュリティ設計を間違えると一瞬で情報漏えいにつながります。 この記事では、SQLiteの暗号化・パスワード・配置・バックアップまで、 現場目線で押さえるべきポイントを整理します。
・SQLiteファイルのセキュリティリスク
・暗号化SQLite(SQLCipherなど)の考え方
・C#アプリでの保護戦略(パスワード・キー管理)
・安全な配置場所と権限設定
・バックアップ時のセキュリティ注意点
・業務アプリ向けベストプラクティス
1. SQLiteのセキュリティリスクを正しく理解する
SQLiteは「.dbファイルをコピーすれば中身が丸見え」という性質があります。 つまり、次のような状況がそのままリスクになります。
- PCが盗難・紛失された
- 共有フォルダにDBを置いている
- バックアップファイルが外部に流出した
2. セキュリティ対策のレイヤー構造
SQLiteのセキュリティは、次のレイヤーで考えると整理しやすいです。
- 物理レイヤー: ファイルの配置場所・OS権限
- 暗号化レイヤー: DBファイル自体の暗号化
- アプリレイヤー: 認証・認可・入力制御
- バックアップレイヤー: コピー・世代管理・持ち出し
この記事では特に①物理+②暗号化+④バックアップを中心に扱います。
3. まずは「配置場所」と「OS権限」を固める
■ やってはいけない配置
- 誰でもアクセスできる共有フォルダ
- デスクトップ直下
- USBメモリなどの外部メディア(暗号化なし)
■ 推奨配置(Windowsデスクトップアプリの場合)
- %LOCALAPPDATA% 配下のアプリ専用フォルダ
- ユーザーごとのプロファイル配下
- アクセス権限を制限したアプリ専用ディレクトリ
「まずはOSレベルで守る」のが最初の一歩です。 そのうえで、必要に応じて暗号化を検討します。
4. SQLiteの暗号化の考え方
標準のSQLiteは暗号化機能を持っていません。 暗号化を行うには、以下のような手段が必要です。
- SQLCipherなどの暗号化対応SQLiteエンジンを使う
- OSやディスクのフルディスク暗号化に頼る
- アプリ側で機微情報だけを別途暗号化して保存する
・「DB全体を守りたい」 → SQLCipherなど暗号化SQLite
・「PCごと守りたい」 → BitLockerなどフルディスク暗号化
・「一部の情報だけ守りたい」 → アプリ側で暗号化して保存
5. C#アプリでの「機微情報だけ暗号化」パターン
「SQLCipher導入までは重いけど、何も守らないのは怖い」 という場合に現実的なのが、特定カラムだけアプリ側で暗号化するパターンです。
■ 例:メールアドレスだけ暗号化して保存
using System.Security.Cryptography;
using System.Text;
public static class CryptoHelper
{
// 実運用ではキーはハードコードせず、OSの保護ストアなどに置く
private static readonly byte[] Key = Encoding.UTF8.GetBytes("your-32byte-secret-key-here!!");
private static readonly byte[] Iv = Encoding.UTF8.GetBytes("your-16byte-iv-here!");
public static string Encrypt(string plain)
{
using var aes = Aes.Create();
aes.Key = Key;
aes.IV = Iv;
using var encryptor = aes.CreateEncryptor();
var bytes = Encoding.UTF8.GetBytes(plain);
var cipher = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
return Convert.ToBase64String(cipher);
}
public static string Decrypt(string cipherText)
{
using var aes = Aes.Create();
aes.Key = Key;
aes.IV = Iv;
using var decryptor = aes.CreateDecryptor();
var bytes = Convert.FromBase64String(cipherText);
var plain = decryptor.TransformFinalBlock(bytes, 0, bytes.Length);
return Encoding.UTF8.GetString(plain);
}
}
■ SQLiteへの保存時
var emailEncrypted = CryptoHelper.Encrypt(user.Email);
var sql = "INSERT INTO Users (Name, Email) VALUES (@name, @mail)";
using var cmd = new SqliteCommand(sql, con);
cmd.Parameters.AddWithValue("@name", user.Name);
cmd.Parameters.AddWithValue("@mail", emailEncrypted);
cmd.ExecuteNonQuery();
■ 読み出し時
var emailEncrypted = reader.GetString(2);
var email = CryptoHelper.Decrypt(emailEncrypted);
この方式なら、DBファイルをコピーされてもメールアドレスは平文で読めない状態にできます。 (ただし、キー管理が甘いと意味がなくなるので注意)
6. キー・パスワードの管理で絶対にやってはいけないこと
■ NGパターン
- 暗号化キーをソースコードにベタ書き
- GitHubなどにキー付きのまま公開
- 設定ファイル(.config)に平文でパスワード記載
■ 現実的な対策案(デスクトップアプリ想定)
- Windowsなら DPAPI(ProtectedData)を利用
- ユーザーごとのローカル設定に暗号化して保存
- アプリ起動時にユーザー入力のパスフレーズからキーを導出
■ DPAPIの簡易例
using System.Security.Cryptography;
using System.Text;
public static class ProtectedStore
{
public static void Save(string path, string plain)
{
var bytes = Encoding.UTF8.GetBytes(plain);
var protectedBytes = ProtectedData.Protect(
bytes, null, DataProtectionScope.CurrentUser);
File.WriteAllBytes(path, protectedBytes);
}
public static string Load(string path)
{
var protectedBytes = File.ReadAllBytes(path);
var bytes = ProtectedData.Unprotect(
protectedBytes, null, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(bytes);
}
}
これにより、同じPCの同じユーザー以外からは復号できない形で秘密情報を保存できます。
7. バックアップ時のセキュリティ注意点
バックアップは「コピーが増える=リスクも増える」ということです。
■ 注意すべきポイント
- バックアップ先のフォルダ権限(誰でも読めないか)
- 外付けHDD・USBメモリへのコピー(紛失リスク)
- クラウドストレージへの同期(共有設定の誤り)
■ 推奨パターン
- バックアップも暗号化されたDBをコピーする
- バックアップフォルダにもOSレベルのアクセス制限
- 持ち出しメディアはフルディスク暗号化(BitLockerなど)
8. ログ・一時ファイルにも注意する
アプリのログや一時ファイルに、 SQLや機微情報をそのまま書き出していないかも要チェックです。
- ログにパスワード・トークン・個人情報を書かない
- 一時ファイルに生データを残さない
- 例外メッセージにSQL全文を出さない(画面表示・ログ両方)
9. 業務アプリ向けベストプラクティスまとめ
- DBファイルはユーザープロファイル配下+権限制限
- 機微情報はアプリ側で暗号化して保存
- 暗号化キーはDPAPIなどで保護し、ベタ書きしない
- バックアップ先にも権限+暗号化を適用
- ログ・一時ファイルに機微情報を残さない
- 必要に応じてSQLCipherなど暗号化SQLiteの採用を検討
まとめ:SQLiteは「軽い」からこそ、セキュリティ設計がすべて
- SQLiteはファイル1つで完結 → コピーされたら中身は丸見え
- まずは配置場所とOS権限で守る
- 次に暗号化(DB全体 or カラム単位)を検討
- キー管理・バックアップ・ログまで含めて設計する
「軽くて便利」なSQLiteは、同時に「軽く持ち出されやすい」DBでもあります。 この記事をベースに、アプリの規模や重要度に合わせて、 無理のないセキュリティレベルを設計してみてください。